﻿/* $RCSFile: MetaDataBuilder.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/MetaDataBuilder.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:32  christian.surieux
 *   Added Log to All cs files
 */

// =======================================================================
//  File: MetadataBuilder.cs
// CSU 24/08/08
// Utilities dedicated to CRM4
// =======================================================================
//  This file is part of Addon Nice product.
//  Copyright (C) Addon Nice.  All rights reserved.
// =======================================================================

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Resources;
using System.Web;
using System.Web.Services.Protocols;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using CrmSdk.CRM4;
using AddonNice.CRMWrapper.Design;
using AddonNice.CRMWrapper.CRM4Meta;

/* From sdk 4.2
Property Maximum number of characters without the concatenated characters 
AttributeMetadata.SchemaName 41 
AttributeMetadata.SchemaName used in the CreateOneToManyRequest.Lookup property which results in the OneToManyRelationship.ReferencingAttribute property  33 
The lookup attribute is created using this schema name + "yominame".
 
EntityMetadata.DisplayName 82 
A saved query (view) is automatically created using the display name + " Advanced Find View". The limit of this saved query name is 100 characters. Be sure to use the string for the correct language.
 
EntityMetadata.SchemaName 39 
The primary key attribute is created automatically using this schema name + "id".
 
EntityMetadata.SchemaName used in the CreateManyToManyRequest.IntersectEntityName property, which results in the ManyToManyMetadata.IntersectEntityName property 39 
The primary key attribute for the intersect table is created automatically using this schema name + "id".
 
RelationshipMetadata.SchemaName 41 
*/

namespace AddonNice.CRMWrapper
{
    /// <summary>
    /// Helper Class to Create entities/attributs/relations/etc with medataservice in v4
    /// </summary>
    public class MetaDataBuilder
    {
        EntityBuilder _eBuilder                 =   null; 
        List<AttributeBuilder> _attList         =   null;
        List<One2ManyRelationBuilder> _relList  =   new List<One2ManyRelationBuilder>();

        bool _Backup                            =   true;

        public bool Backup
        { 
            get
            {
                return _Backup;
            }
            set
            {
                _Backup =   value;
            }
        }

        string _Summary                         =   string.Empty;
        public string Summary
        {
            get
            {
                return _Summary;
            }
        }

        string _Result                         =   string.Empty;
        public string Result
        {
            get
            {
                return _Result;
            }
        }

        public EntityBuilder eBuilder
        {
            get
            {
                return _eBuilder;
            }
        }

        public List<AttributeBuilder> attList
        {
            get
            {
                return _attList;
            }
        }
    
        public List<One2ManyRelationBuilder> relList
        {
            get
            {
                return _relList;
            }
        }

        public MetaDataBuilder(EntityBuilder wBuilder, List<AttributeBuilder> wattList)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder Ctor BEG Entity schemaName: {0}, Attributes Count: {1}",
                    wBuilder.SchemaName,wattList.Count),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            _eBuilder    =   wBuilder; 
            _attList     =   wattList;
        }

        public MetaDataBuilder(EntityBuilder wBuilder, List<AttributeBuilder> wattList, List<One2ManyRelationBuilder> wrelList)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder Ctor BEG Entity schemaName: {0}, Attributes Count: {1}, Relations Count: {2}",
                    wBuilder.SchemaName,wattList.Count,wrelList.Count),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            _eBuilder               =  wBuilder; 
            _attList                =  wattList;
            _relList                =  wrelList;
        }

        public virtual string Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder Prepare BEG Schema: {0}, att count: {1}, rel Count: {2}",_eBuilder.SchemaName,_attList.Count,_relList.Count),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            StringBuilder sb        =    new StringBuilder();
            sb.Append(_eBuilder.Prepare(wrapper4,useBr));
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
            foreach (AttributeBuilder ab in _attList)
            {
                sb.Append(ab.Prepare(wrapper4,useBr));
                sb.Append(nlstr);
                }
            sb.Append(nlstr);
            foreach (One2ManyRelationBuilder rel in _relList)
            {
                sb.Append(rel.Prepare(wrapper4,useBr));
                sb.Append(nlstr);
                }
            sb.Append(nlstr);
            _Summary                =   sb.ToString();
            if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder Prepare END : {0}",_Summary),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            return _Summary;
        }

        public void Build(CRMWrapperBase wrapper4, bool buildEntity,bool publish)
        {
            if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder Build BEG buildEntity: {0}, publish: {1}",buildEntity,publish),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            
            if ( Backup )
            {
                bool ret        =   wrapper4.Util.BackupCustomizations();
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder Build BackupCustomizations success: {0}.",ret),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                // failed, we can't continue without backup
                if (!ret)
                {
                    string msg  =   "[E]MetaDataBuilder Build BackupCustomizations failed, stopping build.";
                    if (CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new Exception(msg);
                }
            }
            
            if ( buildEntity )
                eBuilder.Build(wrapper4,false); // we need to publish the entity to be able to add attributes ???
            StringBuilder sb    =   new StringBuilder();
            sb.AppendFormat("{0} {1}",eBuilder.DisplayName,buildEntity ? "created":"modified");
            sb.Append(CrmStr.strBr);
            if (buildEntity)
            {
                sb.AppendFormat("Created entity ID: '{0}'", eBuilder.EntityID);
                sb.Append(CrmStr.strBr);
                sb.AppendFormat("Created Primary field attribut ID: '{0}'", eBuilder.AttributeId);
                sb.Append(CrmStr.strBr);
            }
            
            foreach (AttributeBuilder att in attList)
            {
                // When doing an update on entity we don't adapt the entity name
                if ( !buildEntity )
                    att.ExistingEntity  =   true;
                att.Build(wrapper4, false);
                sb.AppendFormat("{0} attribute created",att.DisplayName);
                sb.Append(CrmStr.strBr);
            }

            foreach (One2ManyRelationBuilder rel in relList)
            {
                rel.Build(wrapper4, false);
                sb.AppendFormat("{0} lookup created",rel.LookupDisplayName);
                sb.Append(CrmStr.strBr);
            }
            if (publish)
            {
                List<string> ar     =   new List<string>();
                ar.Add(eBuilder.SchemaName);
                wrapper4.Util.PublishEntities(ar);
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder Build Published : {0}",eBuilder.SchemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                sb.AppendFormat("Published.");
                sb.Append(CrmStr.strBr);
                // we must reset metadata cache
                MetadataCache.Reset();
            }
            _Result                 =   sb.ToString();
            if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine("[V]MetaDataBuilder Build END.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
    }

    public class EntityBuilder
    {
        public const int AttributeSchemaNameMaxLen      =   41; 
        public const int EntityDisplayNameMaxLen        =   82;
        public const int EntitySchemaNameMaxLen         =   39 ;
        public const int RelationshipSchemaNameMaxLen   =   41 ;

        bool _TestExists                                =   true;
        bool _prepared                                  =   false;
        string _Summary                                 =   string.Empty;
        EntityMetadata _newEntity                       =   new EntityMetadata();
        CreateEntityResponse entityResponse             =   null;        
        
        string _SchemaName                              =   string.Empty;
        string _DisplayName                             =   string.Empty;
        string _DisplayCollectionName                   =   string.Empty;
        string _Description                             =   string.Empty;
        string _PrimaryFieldName                        =   string.Empty;
        string _PrimaryFieldDisplayName                 =   string.Empty;

        int _langCode                                   =   System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
        
        bool _HasActivities                             =   true;
        bool _HasNotes                                  =   true;
        OwnershipTypes  _ownershipType                  =   OwnershipTypes.UserOwned;

        int _MaxLength                                  =   200;

        #region Properties

        /// <summary>
        /// Set to false when no conditionnal create is necessary
        /// </summary>
        public bool TestExists
        { 
            get
            {
                return _TestExists;
            }
            set
            {
                _TestExists =   value;
            }
        }

        public bool Prepared
        { 
            get
            {
                return _prepared;
            }
        }

        public string Summary
        {
            get
            {
                return _Summary;
            }
        }

        public EntityMetadata newEntity    
        { 
            get
            {
                return _newEntity;
            }
        }
        
        public string SchemaName          
        { 
            get
            {
                return _SchemaName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder SchemaName max len is 39.";
                    throw new ArgumentException(msg);
                }
                _SchemaName =   value;
            }
        }

        public string DisplayName
        { 
            get
            {
                return _DisplayName;
            }
            set
            {
                if ( value.Length > EntityDisplayNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder DisplayName max len is 82.";
                    throw new ArgumentException(msg);
                }
                _DisplayName =   value;
            }
        }

        public string DisplayCollectionName 
        { 
            get
            {
                return _DisplayCollectionName;
            }
            set
            {
                if ( value.Length > EntityDisplayNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder DisplayCollectionName max len is 82.";
                    throw new ArgumentException(msg);
                }
                _DisplayCollectionName =   value;
            }
        }

        public string Description
        { 
            get
            {
                return _Description;
            }
            set
            {
                _Description    =   value;
            }
        }

        
        public string PrimaryFieldName
        { 
            get
            {
                return _PrimaryFieldName;
            }
            set
            {
                if ( value.Length > AttributeSchemaNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder PrimaryFieldName max len is 41.";
                    throw new ArgumentException(msg);
                }
                _PrimaryFieldName =   value;
            }
        }

        public string PrimaryFieldDisplayName
        { 
            get
            {
                return _PrimaryFieldDisplayName;
            }
            set
            {
                _PrimaryFieldDisplayName    =   value;
            }
        }
        
        /// <summary>
        /// Defaults to System.Threading.Thread.CurrentThread.CurrentCulture
        /// </summary>
        public int LangCode
        { 
            get
            {
                return _langCode;
            }
            set
            {
                _langCode =   value;
            }
        }

        /// <summary>
        /// Defaults to true
        /// </summary>
        public bool HasActivities
        { 
            get
            {
                return _HasActivities;
            }
            set
            {
                _HasActivities =   value;
            }
        }

        /// <summary>
        /// Defaults to true
        /// </summary>
        public bool HasNotes             
        { 
            get
            {
                return _HasNotes;
            }
            set
            {
                _HasNotes =   value;
            }
        }
        
        /// <summary>
        /// Defaults to UserOwned
        /// </summary>
        public OwnershipInternalTypes  OwnershipType
        { 
            get
            {
                return (OwnershipInternalTypes)(int)_ownershipType;
            }
            set
            {
                _ownershipType      = (OwnershipTypes)(int) value;
            }
        }
            
        public int MaxLength
        { 
            get
            {
                return _MaxLength;
            }
            set
            {
                _MaxLength =   value;
            }
        }

        /// <summary>
        /// Return value after Build
        /// </summary>
        public Guid EntityID
        {
            get
            {
                if (entityResponse != null)
                    return entityResponse.EntityId.Value;
                return Guid.Empty;
            }
        }

        /// <summary>
        /// Return value after Build
        /// </summary>
        public Guid AttributeId
        {
            get
            {
                if (entityResponse != null)
                    return entityResponse.AttributeId.Value;
                return Guid.Empty;
            }
        }
        
        #endregion Properties
            
        public EntityBuilder(string schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MetaDataBuilder EntityBuilder BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            SchemaName = schemaName;
            }
        
        public string Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            string DefaultDescription = string.Format("Created by AddonNice on {0}.", DateTime.Now);
            if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Prepare BEG _Prepared: {0}",_prepared),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( _prepared )
                return string.Empty;
            StringBuilder sb                                =   new StringBuilder();
            try
            {
                string currentPrefix                        =   CrmStr.AdnPrefix;
                string oldPrefix                            =   wrapper4.SchemaNamePrefix;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Prepare oldPrefix: {0}",oldPrefix),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

                // Create the entity.
                string wschemaName                          =   SchemaName.Replace(" ",string.Empty);
                if ( !wschemaName.StartsWith(currentPrefix+"_") )
                    wschemaName                             =   string.Format("{0}_{1}",currentPrefix,wschemaName);
                SchemaName                                  =   wschemaName; // to bring back changes to caller

                   
                wschemaName                                 =   PrimaryFieldName.Replace(" ",string.Empty);
                if ( !wschemaName.StartsWith(currentPrefix+"_") )
                    wschemaName                             =   string.Format("{0}_{1}",currentPrefix,wschemaName);
                PrimaryFieldName                            =   wschemaName; // to bring back changes to caller
                string nlstr                                =   Environment.NewLine;
                if ( useBr )
                        nlstr                               =   CrmStr.strBr;

                sb.AppendFormat("Entity Schema Name: {0}, Display Name: {1}, Display Collection Name: {2}{3}",
                        new object[]{SchemaName,DisplayName,DisplayCollectionName,nlstr});
                sb.AppendFormat("Primary Field Name: {0}, Display Name: {1}, Max. Length: {2}{3}",
                        new object[]{PrimaryFieldName,PrimaryFieldDisplayName,MaxLength,nlstr});
                sb.AppendFormat("HasActivities: {0}, HasNotes: {1}.{2}",HasActivities,HasNotes,nlstr);
                sb.AppendFormat("Description: {0}{1}",Description,nlstr);
                sb.Append(nlstr);
                _prepared                                   =   true;
            }
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]MetaDataBuilder EntityBuilder ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
            _Summary                                        =  sb.ToString();
            return _Summary;
        }

        public void Build(CRMWrapperBase wrapper4, bool publish)
        {
            string DefaultDescription                       =   string.Format("Created by AddonNice on {0}.", DateTime.Now);
            try
            {
                string currentPrefix                        =   CrmStr.AdnPrefix;
                string oldPrefix                            =   wrapper4.SchemaNamePrefix;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Build oldPrefix: {0}, Prepared: {1}",oldPrefix,_prepared),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                bool changed                                =   false;
                // TD Get AddonNice prefix from settings
                if (!oldPrefix.Equals(currentPrefix))
                {
                    wrapper4.Util.UpdateSchemaPrefix(currentPrefix);
                    changed                                 =   true;
                }

                if ( !Prepared )
                    Prepare(wrapper4,false);


                // Create the entity.
                newEntity.SchemaName                        =   SchemaName; 
                newEntity.OwnershipType                     =   new CrmOwnershipTypes();
                newEntity.OwnershipType.Value               =   _ownershipType;
                //newEntity.LogicalName                       =   wschemaName.ToLower();
                newEntity.DisplayName                       =   CRMUtil4.CreateSingleLabel(DisplayName, LangCode);
                newEntity.DisplayCollectionName             =   CRMUtil4.CreateSingleLabel(DisplayCollectionName, LangCode);
                newEntity.Description                       =   CRMUtil4.CreateSingleLabel((Description == string.Empty) ? DefaultDescription:Description, LangCode);

                // Create the primary attribute.
                StringAttributeMetadata primaryAtt          =   new StringAttributeMetadata();
                primaryAtt.MaxLength                        =   new CrmNumber();
                primaryAtt.MaxLength.Value                  =   MaxLength;
                   
                primaryAtt.SchemaName                       =   PrimaryFieldName;
                primaryAtt.RequiredLevel                    =   new CRM4Meta.CrmAttributeRequiredLevel();
                primaryAtt.RequiredLevel.Value              =   AttributeRequiredLevel.None;

                primaryAtt.EntityLogicalName                =   SchemaName.ToLower();
                primaryAtt.LogicalName                      =   PrimaryFieldName.ToLower();
                primaryAtt.DisplayName                      =   CRMUtil4.CreateSingleLabel(PrimaryFieldDisplayName, LangCode);
                primaryAtt.Description                      =   CRMUtil4.CreateSingleLabel(DefaultDescription, LangCode);

                // Create the entity request.
                CreateEntityRequest createEntity            =   new CreateEntityRequest();
                createEntity.Entity                         =   newEntity;
                createEntity.HasActivities                  =   HasActivities;
                createEntity.HasNotes                       =   HasNotes;
                createEntity.PrimaryAttribute               =   primaryAtt;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Build SchemaName: {0}, DisplayName: {1}, LangCode: {2}, PrimaryFieldName: {3}, MaxLength: {4}, PrimaryFieldDisplayName: {5}",
                        new object[]{newEntity.SchemaName,DisplayName, LangCode,primaryAtt.SchemaName,MaxLength,PrimaryFieldDisplayName}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

                
                // Execute the request.
                if ( wrapper4 is CrmWrapper4 )
                {
                    // if test is requested
                    if ( TestExists )
                    {
                        try
                        {
                            EntityInternalMetadata exent    =  wrapper4.adminRetrieveEntityMetadata(SchemaName,EntityInternalItems.EntityOnly);
				            if ( CRMMetaTrace.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Build END SchemaName: {0} existing Entity skipping create.",
                                    SchemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                            if ( changed )
                                wrapper4.Util.UpdateSchemaPrefix(oldPrefix);
                            return;
                        }
                        catch (CRMNotFoundException)
			            {
				            if ( CRMMetaTrace.Sw.TraceVerbose )
                                Trace.WriteLine( "[V]EntityBuilder Build TestExists doesn't exist.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                            // Normal we continue with create
			            }
                        catch (Exception ex)
			            {
				            if ( CRMMetaTrace.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Build TestExists ex : {0}", ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                            // Normal we continue with create
			            }
                    }

                    entityResponse                          =   (CreateEntityResponse)((CrmWrapper4)wrapper4).adminMetaExecuteRaw(createEntity);
                    if ( changed )
                        wrapper4.Util.UpdateSchemaPrefix(oldPrefix);
                    if (publish)
                    {
                        List<string> ar = new List<string>();
                        ar.Add(newEntity.SchemaName);
                        wrapper4.Util.PublishEntities(ar);
                        if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Build Published : {0}",newEntity.SchemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    }
                    if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EntityBuilder Built END : {0}",newEntity.SchemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                }
                else 
                {
                    const string msg    =   "[E]EntityBuilder NOT available for CRM 3";
                    if (CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine(msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new Exception(msg);
                }
            }
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]EntityBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
        }
    }
    
    public class AttributeBuilder
    {
        public const int AttributeSchemaNameMaxLen      =   41; 
        public const int EntityDisplayNameMaxLen        =   82;
        public const int EntitySchemaNameMaxLen         =   39 ;

        protected bool _TestExists                      =   true;
        protected bool _ExistingEntity                  =   false;
        protected bool _prepared                        =   false;
        protected string _Summary                       =   string.Empty;

        protected AttributeMetadata _newAttribute       =   null;
        
        string _EntityName                              =   string.Empty;
        string _SchemaName                              =   string.Empty;
        string _DisplayName                             =   string.Empty;
        string _DisplayCollectionName                   =   string.Empty;
        string _Description                             =   string.Empty;

        int _langCode                                   =   System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
        protected ImeMode _AttImeMode                   =   ImeMode.Disabled;

        int _Precision                                  =   2;
        int _PrecisionSource                            =   1; // TBC which value for pricingdecimalprecision
        int _MaxLength                                  =   200;
        int _MaxValue                                   =   int.MaxValue;
        int _MinValue                                   =   int.MinValue;
        double _MaxMoneyValue                           =   100000000000d;//(double)decimal.MaxValue;// double.MaxValue;
        double _MinMoneyValue                           =   -100000000000d;//(double)decimal.MinValue;
        protected DateTimeFormat _DateFormat            =   DateTimeFormat.DateAndTime;
        protected StringFormat _TextFormat              =   StringFormat.Text;
        protected IntegerFormat _IntFormat              =   IntegerFormat.None;

        protected string _FalseOptionText               =   false.ToString(System.Threading.Thread.CurrentThread.CurrentCulture);
        protected int _FalseOptionValue                 =   0;
        protected string _TrueOptionText                =   true.ToString(System.Threading.Thread.CurrentThread.CurrentCulture);
        protected int _TrueOptionValue                  =   1;

        protected string[] _PickListOptions             =   new string[0];

        #region Properties

        /// <summary>
        /// Set to false when no conditionnal create is necessary
        /// </summary>
        public bool TestExists
        { 
            get
            {
                return _TestExists;
            }
            set
            {
                _TestExists =   value;
            }
        }

        /// <summary>
        /// When updating an existing entity, set this flag to true to avoid change in EntityName
        /// during Prepare
        /// </summary>
        public bool ExistingEntity
        { 
            get
            {
                return _ExistingEntity;
            }
            set
            {
                _ExistingEntity =   value;
            }
        }

        public bool Prepared
        { 
            get
            {
                return _prepared;
            }
        }

        public string Summary
        {
            get
            {
                return _Summary;
            }
        }

        protected string DefaultDescription
        {
            get
            {
                return string.Format("Created by AddonNice on {0}.", DateTime.Now);
            }
        }

        #region common parameters
        
        public AttributeMetadata newAttribute    
        { 
            get
            {
                return _newAttribute;
            }
        }
        
        public string EntityName          
        { 
            get
            {
                return _EntityName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder EntityName max len is 41.";
                    throw new ArgumentException(msg);
                }
                _EntityName =   value;
            }
        }

        public string SchemaName          
        { 
            get
            {
                return _SchemaName;
            }
            set
            {
                if ( value.Length > AttributeSchemaNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder SchemaName max len is 41.";
                    throw new ArgumentException(msg);
                }
                _SchemaName =   value;
            }
        }

        public string DisplayName
        { 
            get
            {
                return _DisplayName;
            }
            set
            {
                if ( value.Length > EntityDisplayNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder DisplayName max len is 82.";
                    throw new ArgumentException(msg);
                }
                _DisplayName =   value;
            }
        }

        public string DisplayCollectionName 
        { 
            get
            {
                return _DisplayCollectionName;
            }
            set
            {
                if ( value.Length > EntityDisplayNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder DisplayCollectionName max len is 82.";
                    throw new ArgumentException(msg);
                }
                _DisplayCollectionName =   value;
            }
        }

        public string Description
        { 
            get
            {
                return _Description;
            }
            set
            {
                _Description    =   value;
            }
        }
        
        public AttributeType  _AttType  =    AttributeType.String;
        /// <summary>
        /// Defaults to string
        /// </summary>
        public AttributeInternalType  AttType 
        { 
            get
            {
                switch (_AttType)
                {
                    case AttributeType.Boolean:
                    return AttributeInternalType.Boolean;
                    case AttributeType.DateTime:
                    return AttributeInternalType.DateTime;
                    case AttributeType.Decimal:
                    return AttributeInternalType.Decimal;
                    case AttributeType.Float:
                    return AttributeInternalType.Float;
                    case AttributeType.Integer:
                    return AttributeInternalType.Integer;
                    case AttributeType.Memo:
                    return AttributeInternalType.Memo;
                    case AttributeType.Money:
                    return AttributeInternalType.Money;
                    case AttributeType.Picklist:
                    return AttributeInternalType.Picklist;
                    default:
                    case AttributeType.String:
                    return AttributeInternalType.String;
                }
            }
            set
            {
                switch (value)
                {
                    case AttributeInternalType.Boolean:
                    _AttType =   AttributeType.Boolean;
                    break;
                    case AttributeInternalType.DateTime:
                    _AttType =   AttributeType.DateTime;
                    break;
                    case AttributeInternalType.Decimal:
                    _AttType =   AttributeType.Decimal;
                    break;
                    case AttributeInternalType.Float:
                    _AttType =   AttributeType.Float;
                    break;
                    case AttributeInternalType.Integer:
                    _AttType =   AttributeType.Integer;
                    break;
                    case AttributeInternalType.Memo:
                    _AttType =   AttributeType.Memo;
                    break;
                    case AttributeInternalType.Money:
                    _AttType =   AttributeType.Money;
                    break;
                    case AttributeInternalType.Picklist:
                    _AttType =   AttributeType.Picklist;
                    break;
                    case AttributeInternalType.String:
                    _AttType =   AttributeType.String;
                    break;
                }
            }
        }

        public int LangCode
        { 
            get
            {
                return _langCode;
            }
            set
            {
                _langCode =   value;
            }
        }
            
        /// <summary>
        /// Defaults to Disabled
        /// </summary>
        public ImeInternalMode AttImeMode
        { 
            get
            {
                return (ImeInternalMode)(int)_AttImeMode;
            }
            set
            {
                _AttImeMode =  (ImeMode)(int) value;
            }
        }

        #endregion common parameters
        
        #region String/ Memo/Integer
        
        /// <summary>
        /// Defaults to 200
        /// </summary>
        public int MaxLength
        { 
            get
            {
                return _MaxLength;
            }
            set
            {
                _MaxLength =   value;
            }
        }

        public StringInternalFormat TextFormat
        { 
            get
            {
                return (StringInternalFormat)(int)_TextFormat;
            }
            set
            {
                _TextFormat =   (StringFormat)(int)value;
            }
        }

        /// <summary>
        /// Defaults to None
        /// </summary>
        public IntegerInternalFormat IntFormat
        { 
            get
            {
                return (IntegerInternalFormat)(int)_IntFormat;
            }
            set
            {
                _IntFormat =   (IntegerFormat)(int)value;
            }
        }

        public int MaxValue
        { 
            get
            {
                return _MaxValue;
            }
            set
            {
                _MaxValue =   value;
            }
        }

        public int MinValue
        { 
            get
            {
                return _MinValue;
            }
            set
            {
                _MinValue =   value;
            }
        }

        #endregion String/ Memo/Integer

        #region bool
        
        public string FalseOptionText
        { 
            get
            {
                return _FalseOptionText;
            }
            set
            {
                _FalseOptionText =   value;
            }
        }

        public int FalseOptionValue
        { 
            get
            {
                return _FalseOptionValue;
            }
            set
            {
                _FalseOptionValue =   value;
            }
        }

        public string TrueOptionText
        { 
            get
            {
                return _TrueOptionText;
            }
            set
            {
                _TrueOptionText =   value;
            }
        }

        public int TrueOptionValue
        { 
            get
            {
                return _TrueOptionValue;
            }
            set
            {
                _TrueOptionValue =   value;
            }
        }

        #endregion bool

        #region Money/Double/Float/Decimal

        public double MaxMoneyValue
        { 
            get
            {
                return _MaxMoneyValue;
            }
            set
            {
                _MaxMoneyValue =   value;
            }
        }

        public double MinMoneyValue
        { 
            get
            {
                return _MinMoneyValue;
            }
            set
            {
                _MinMoneyValue =   value;
            }
        }

        /// <summary>
        /// Defaults to 2
        /// </summary>
        public int Precision
        { 
            get
            {
                return _Precision;
            }
            set
            {
                if (value < 0)
                {
                    string msg  =   "[E]MetaDataBuilder Precision must be > 0.";
                    throw new ArgumentException(msg);
                }
                _Precision =   value;
            }
        }
        
        public int PrecisionSource
        { 
            get
            {
                return _PrecisionSource;
            }
            set
            {
                _PrecisionSource =   value;
            }
        }
        #endregion Money/Double/Float/Decimal

        #region DateTime

        public DateTimeInternalFormat DateFormat
        {
            get
            {
                return (DateTimeInternalFormat)(int)_DateFormat;
            }
            set
            {
                _DateFormat =   (DateTimeFormat)(int)value;
            }
        }
        #endregion DateTime

        #region pickList

        public string[] PickListOptions
        {
            get
            {
                return _PickListOptions;
            }
            set
            {
                if ( value !=null )
                    _PickListOptions =   value;
            }
        }

        #endregion pickList
        
        #endregion Properties

        public AttributeBuilder(string entityName,string schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            EntityName  =   entityName;
            SchemaName  =   schemaName;
        }
        
        public virtual string Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Prepare BEG _Prepared: {0}",_prepared),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( _prepared )
                return string.Empty;
            StringBuilder sb                                        =   new StringBuilder();
            try
            {
                string currentPrefix                                =   CrmStr.AdnPrefix;
                string oldPrefix                                    =   wrapper4.SchemaNamePrefix;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Prepare oldPrefix: {0}",oldPrefix),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                
                string wschemaName                                  =   EntityName.Replace(" ",string.Empty);
                if (  !ExistingEntity && !wschemaName.StartsWith(currentPrefix+"_") )
                    wschemaName                                     =   string.Format("{0}_{1}",currentPrefix,wschemaName);
                EntityName                                          =   wschemaName; // to bring back changes to caller
                
                wschemaName                                         =   SchemaName.Replace(" ",string.Empty);
                if ( !wschemaName.StartsWith(currentPrefix+"_") )
                    wschemaName                                     =   string.Format("{0}_{1}",currentPrefix,wschemaName);
                SchemaName                                          =   wschemaName; // to bring back changes to caller
                
                string nlstr                                        =   Environment.NewLine;
                if ( useBr )
                        nlstr                                       =   CrmStr.strBr;

                sb.AppendFormat("SchemaName: {0}, DisplayName: {1}, DisplayCollectionName: {2}{3}",
                    new object[]{SchemaName,DisplayName, DisplayCollectionName,nlstr});
                
                _prepared                                           =   true;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine("[V]AttributeBuilder Prepare END.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AttributeBuilder Prepare ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
            return sb.ToString();
        }

        public virtual void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                string currentPrefix                                =   CrmStr.AdnPrefix;
                string oldPrefix                                    =   wrapper4.SchemaNamePrefix;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Build BEG oldPrefix: {0}",oldPrefix),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                bool changed                                        =   false;
                // TD Get AddonNice prefix from settings
                if (!oldPrefix.Equals(currentPrefix))
                {
                    wrapper4.Util.UpdateSchemaPrefix(currentPrefix);
                    changed                                         =   true;
                }

                if ( !_prepared )
                    Prepare(wrapper4,false);

                // Create the entity.
                _newAttribute.SchemaName                            =   SchemaName;
                _newAttribute.RequiredLevel                         =   new CRM4Meta.CrmAttributeRequiredLevel();
                _newAttribute.RequiredLevel.Value                   =   AttributeRequiredLevel.None;

                _newAttribute.EntityLogicalName                     =   EntityName.ToLower();
                _newAttribute.LogicalName                           =   SchemaName.ToLower();
                _newAttribute.DisplayName                           =   CRMUtil4.CreateSingleLabel(DisplayName, LangCode);
                _newAttribute.Description                           =   CRMUtil4.CreateSingleLabel(DefaultDescription, LangCode);

                // Create the entity request.
                CreateAttributeRequest createAttribute              =   new CreateAttributeRequest();
                createAttribute.EntityName                          =   EntityName;
                createAttribute.Attribute                           =   _newAttribute;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Build SchemaName: {0}, DisplayName: {1}, LangCode: {2}, EntityName: {3}",
                        new object[]{_newAttribute.SchemaName,DisplayName, LangCode,EntityName}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                // Execute the request.
                if ( wrapper4 is CrmWrapper4 )
                {
                    // if test is requested
                    if ( TestExists )
                    {
                        try
                        {
                            InternalAttributeMetadata exatt   =  wrapper4.adminRetrieveAttributeMetadata(_newAttribute.EntityLogicalName,_newAttribute.SchemaName);
				            if ( CRMMetaTrace.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Build END SchemaName: {0} existing attribute skipping create.",
                                    _newAttribute.SchemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                            if ( changed )
                                wrapper4.Util.UpdateSchemaPrefix(oldPrefix);
                            return;
                        }
                        catch (CRMNotFoundException)
			            {
				            if ( CRMMetaTrace.Sw.TraceVerbose )
                                Trace.WriteLine( "[V]AttributeBuilder Build TestExists doesn't exist.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                            // Normal we continue with create
			            }
                        catch (Exception ex)
			            {
				            if ( CRMMetaTrace.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Build TestExists ex : {0}", ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                            // Normal we continue with create
			            }
                    }

                    ((CrmWrapper4)wrapper4).adminMetaExecuteRaw(createAttribute);
                    if ( changed )
                        wrapper4.Util.UpdateSchemaPrefix(oldPrefix);
                    if (publish)
                    {
                        List<string> ar     =   new List<string>();
                        ar.Add(_newAttribute.EntityLogicalName);
                        wrapper4.Util.PublishEntities(ar);
                        if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilderBuild  Published : {0}",_newAttribute.EntityLogicalName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    }
                    if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Build END Built: {0}",_newAttribute.EntityLogicalName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                }
                else 
                {
                    const string msg    =   "[E]AttributeBuilder NOT available for CRM 3";
                    if (CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine(msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new Exception(msg);
                }
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }

    public class StringAttributeBuilder : AttributeBuilder
    {
        public StringAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]StringAttributeBuilder Ctor BEG entityName: {0}, schemaName: {1}",entityName,schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }

        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb        =   new StringBuilder();
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append("Attribute String");
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("Format: {0}, Max length: {1}{2}",TextFormat,MaxLength,nlstr);
            sb.Append(nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
        }
        
        /// <summary>
        /// Needs MaxLength, Format, ImeMode
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                // Create the primary attribute.
                StringAttributeMetadata primaryAtt          =   new StringAttributeMetadata();
                _newAttribute                               =   primaryAtt;
                primaryAtt.MaxLength                        =   new CrmNumber();
                primaryAtt.MaxLength.Value                  =   MaxLength;
                primaryAtt.Format                           =   new CrmStringFormat();
                primaryAtt.Format.Value                     =   _TextFormat;
				primaryAtt.ImeMode                          =   new CrmImeMode();
				primaryAtt.ImeMode.Value                    =   _AttImeMode;

                primaryAtt.AttributeType                    =   new CRM4Meta.CrmAttributeType();
				primaryAtt.AttributeType.Value              =   AttributeType.String;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]StringAttributeBuilder Build MaxLength: {0}, _TextFormat: {1}, _AttImeMode: {2}",
                        new object[]{MaxLength, _TextFormat,_AttImeMode}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]StringAttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }
        
    public class MemoAttributeBuilder : AttributeBuilder
    {

        public MemoAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MemoAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute Memo");
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("Format: {0}, Max length: {1}",TextFormat,MaxLength);
            sb.Append(nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
        }

        /// <summary>
        /// Needs MaxLength, Format
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                // Create the primary attribute.
                MemoAttributeMetadata primaryAtt            =   new MemoAttributeMetadata();
                _newAttribute                               =   primaryAtt;
                primaryAtt.MaxLength                        =   new CrmNumber();
                primaryAtt.MaxLength.Value                  =   MaxLength;
                primaryAtt.Format                           =   new CrmStringFormat();
                primaryAtt.Format.Value                     =   StringFormat.TextArea;
				primaryAtt.ImeMode                          =   new CrmImeMode();
				primaryAtt.ImeMode.Value                    =   _AttImeMode;

                primaryAtt.AttributeType                    =   new CRM4Meta.CrmAttributeType();
				primaryAtt.AttributeType.Value              =   AttributeType.Memo;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MemoAttributeBuilder Build MaxLength: {0}, _TextFormat: {1}, _AttImeMode: {2}",
                        new object[]{MaxLength, _TextFormat,_AttImeMode}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]MemoAttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }
        
    public class IntegerAttributeBuilder : AttributeBuilder
    {

        public IntegerAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]IntegerAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute Integer");
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("Format: {0}, Max value: {1}, Min value: {2}{3}",
                new object[]{TextFormat,MaxValue,MinValue,nlstr});
            sb.Append(nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
            }

        /// <summary>
        /// Needs MaxValue, MinValue, IntFormat
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                IntegerAttributeMetadata primaryAttribute   =   new IntegerAttributeMetadata ();
                _newAttribute                               =   primaryAttribute;
                primaryAttribute.MaxValue                   =   new CrmNumber();
                primaryAttribute.MaxValue.Value             =   MaxValue;
                primaryAttribute.MinValue                   =   new CrmNumber();
                primaryAttribute.MinValue.Value             =   MinValue;
                primaryAttribute.Format                     =   new CrmIntegerFormat();
				primaryAttribute.Format.Value               =   _IntFormat;

                primaryAttribute.AttributeType              =   new CRM4Meta.CrmAttributeType();
				primaryAttribute.AttributeType.Value        =   AttributeType.Integer;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]IntegerAttributeBuilder Build MaxValue: {0}, MinValue: {1}, _IntFormat: {2}",
                        new object[]{MaxValue,MinValue, _IntFormat}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]IntegerAttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }

    public class DateTimeAttributeBuilder : AttributeBuilder
    {

        public DateTimeAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DateTimeAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute DataTime");
            string nlstr        =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("Format: {0}{1}",_DateFormat,nlstr);
            sb.Append(nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
        }

        /// <summary>
        /// Needs DateFormat, ImeMode (Default None)
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                DateTimeAttributeMetadata primaryAttribute   =   new DateTimeAttributeMetadata();
                _newAttribute                               =   primaryAttribute;
                primaryAttribute.Format                     =   new CrmDateTimeFormat();
                primaryAttribute.Format.Value               =   _DateFormat;
				primaryAttribute.ImeMode                    =   new CrmImeMode();
				primaryAttribute.ImeMode.Value              =   _AttImeMode;

                primaryAttribute.AttributeType              =   new CRM4Meta.CrmAttributeType();
				primaryAttribute.AttributeType.Value        =   AttributeType.DateTime;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DateTimeAttributeBuilder Build _DateFormat: {0}, _AttImeMode: {1}",
                        new object[]{_DateFormat,_AttImeMode}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]MetaDataBuilder IntegerAttributeBuilder ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }

    public class MoneyAttributeBuilder : AttributeBuilder
    {
        public MoneyAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MoneyAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute Money");
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("Max value: {0}, Min value: {1}, Precision: {2}{3}",
                new object[]{MaxMoneyValue,MinMoneyValue,Precision,nlstr});
            sb.Append(nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
            }

        /// <summary>
        /// Needs MaxValue, MinValue, Precision, PrecisionSource (Default Ok), ImeMode (Default Ok)
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                MoneyAttributeMetadata primaryAttribute     =   new MoneyAttributeMetadata();
                _newAttribute                               =   primaryAttribute;
                primaryAttribute.MaxValue                   =   new CrmDouble();
                primaryAttribute.MaxValue.Value             =   MaxMoneyValue;
                primaryAttribute.MinValue                   =   new CrmDouble();
                primaryAttribute.MinValue.Value             =   MinMoneyValue;
                primaryAttribute.Precision                  =   new CrmNumber();
                primaryAttribute.Precision.Value            =   Precision;
                primaryAttribute.PrecisionSource            =   new CrmNumber();
				primaryAttribute.PrecisionSource.Value      =   PrecisionSource; // ???
				primaryAttribute.ImeMode                    =   new CrmImeMode();
				primaryAttribute.ImeMode.Value              =   _AttImeMode;

                primaryAttribute.AttributeType              =   new CRM4Meta.CrmAttributeType();
				primaryAttribute.AttributeType.Value        =   AttributeType.Money;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]MoneyAttributeBuilder Build MaxMoneyValue: {0}, MinMoneyValue: {1}, Precision: {2}",
                        new object[]{MaxMoneyValue,MinMoneyValue, Precision}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]MoneyAttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }
    
    public class FloatAttributeBuilder : AttributeBuilder
    {
        public FloatAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]FloatAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute Float");
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("Max value: {0}, Min value: {1}, Precision: {2}",MaxMoneyValue,MinMoneyValue,Precision);
            sb.Append(nlstr+nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
        }

        /// <summary>
        /// Needs MaxValue, MinValue, Precision, ImeMode (default None)
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                FloatAttributeMetadata primaryAttribute     =   new FloatAttributeMetadata();
                _newAttribute                               =   primaryAttribute;
                primaryAttribute.MaxValue                   =   new CrmFloat();
                primaryAttribute.MaxValue.Value             =   MaxMoneyValue;
                primaryAttribute.MinValue                   =   new CrmFloat();
                primaryAttribute.MinValue.Value             =   MinMoneyValue;
                primaryAttribute.Precision                  =   new CrmNumber();
                primaryAttribute.Precision.Value            =   Precision;
				primaryAttribute.ImeMode                    =   new CrmImeMode();
				primaryAttribute.ImeMode.Value              =   _AttImeMode;

                primaryAttribute.AttributeType              =   new CRM4Meta.CrmAttributeType();
				primaryAttribute.AttributeType.Value        =   AttributeType.Float;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]FloatAttributeBuilder Build MaxMoneyValue: {0}, MinMoneyValue: {1}, Precision: {2}",
                        new object[]{MaxMoneyValue,MinMoneyValue, Precision}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]FloatAttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }

    public class DecimalAttributeBuilder : AttributeBuilder
    {
        public DecimalAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DecimalAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute Decimal");
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("Max value: {0}, Min value: {1}, Precision: {2}",MaxMoneyValue,MinMoneyValue,Precision);
            sb.Append(nlstr+nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
        }

        /// <summary>
        /// Needs MaxValue, MinValue, Precision
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                DecimalAttributeMetadata primaryAttribute   =   new DecimalAttributeMetadata();
                _newAttribute                               =   primaryAttribute;
                primaryAttribute.MaxValue                   =   new CrmDouble();
                primaryAttribute.MaxValue.Value             =   MaxMoneyValue;
                primaryAttribute.MinValue                   =   new CrmDouble();
                primaryAttribute.MinValue.Value             =   MinMoneyValue;
                primaryAttribute.Precision                  =   new CrmNumber();
                primaryAttribute.Precision.Value            =   Precision;
				
                primaryAttribute.AttributeType              =   new CRM4Meta.CrmAttributeType();
				primaryAttribute.AttributeType.Value        =   AttributeType.Decimal;

                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DecimalAttributeBuilder Build MaxMoneyValue: {0}, MinMoneyValue: {1}, Precision: {2}",
                        new object[]{MaxMoneyValue,MinMoneyValue, Precision}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]DecimalAttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }

    public class BoolAttributeBuilder : AttributeBuilder
    {
        public BoolAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]BoolAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute Bool");
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.AppendFormat("True option Text: {0}, value: {1}, False option value: {2}, value: {3}",
                new object[]{TrueOptionText,TrueOptionValue,FalseOptionText,FalseOptionValue});
            sb.Append(nlstr+nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
        }

        /// <summary>
        /// Needs FalseOptionValue, FalseOptionText, TrueOptionValue, TrueOptionText
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                BooleanAttributeMetadata primaryAttribute   =   new BooleanAttributeMetadata();
                _newAttribute                               =   primaryAttribute;

                primaryAttribute.FalseOption                =   new Option();
                primaryAttribute.FalseOption.Label          =   CRMUtil4.CreateSingleLabel(FalseOptionText,LangCode);
                primaryAttribute.FalseOption.Value          =   new CrmNumber();
                primaryAttribute.FalseOption.Value.Value    =   FalseOptionValue;
                primaryAttribute.TrueOption                 =   new Option();
                primaryAttribute.TrueOption.Label           =   CRMUtil4.CreateSingleLabel(TrueOptionText,LangCode);
                primaryAttribute.TrueOption.Value           =   new CrmNumber();
                primaryAttribute.TrueOption.Value.Value     =   TrueOptionValue;

				primaryAttribute.AttributeType              =   new CRM4Meta.CrmAttributeType();
				primaryAttribute.AttributeType.Value        =   AttributeType.Boolean;
                
                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]DecimalAttributeBuilder Build FalseOptionText: {0}, FalseOptionValue: {1}, TrueOptionText: {2}, TrueOptionValue: {3}",
                        new object[]{FalseOptionText,FalseOptionValue, TrueOptionText,TrueOptionValue}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);

                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]BooleanAttributeMetadata Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }

    public class PickListAttributeBuilder : AttributeBuilder
    {
        public PickListAttributeBuilder(string entityName,string schemaName) : base(entityName,schemaName)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PickListAttributeBuilder Ctor BEG schemaName: {0}",schemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
        }
        
        public override string  Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            StringBuilder sb    =   new StringBuilder();
            sb.Append("Attribute PickList");
            string nlstr            =   useBr ? CrmStr.strBr:Environment.NewLine;
            sb.Append(nlstr);
 	        sb.Append(base.Prepare(wrapper4,useBr));
            sb.Append("Options:");
            sb.Append(nlstr);
			for (int i = 0; i < PickListOptions.Length; i++)
			{
                sb.AppendFormat("Text: {0}, Value: {1}.",PickListOptions[i],i+1);
                sb.Append(nlstr);
			}
            sb.Append(nlstr);
            _Summary            =   sb.ToString();
            return _Summary;
        }

        /// <summary>
        /// Needs array of value
        /// </summary>
        public override void Build(CRMWrapperBase wrapper4, bool publish)
        {
            try
            {
                PicklistAttributeMetadata primaryAttribute  =   new PicklistAttributeMetadata();
                _newAttribute                               =   primaryAttribute;
                primaryAttribute.Options                    =   new Option[PickListOptions.Length];
                if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PickListAttributeBuilder Build PickListOptions.Length: {0}",PickListOptions.Length),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
				for (int i = 0; i < PickListOptions.Length; i++)
				{
					Option picklistOption                   =   new Option();
					picklistOption.Value                    =   new CrmNumber();
					picklistOption.Value.Value              =   i + 1;
					picklistOption.Label                    =   CRMUtil4.CreateSingleLabel(PickListOptions[i],LangCode);
					primaryAttribute.Options[i]             =   picklistOption;
                    if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PickListAttributeBuilder Build ,PickListOptions[{0}]: {1}, LangCode: {2}",
                            i,PickListOptions[i],LangCode),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
				}
				primaryAttribute.AttributeType              =   new CRM4Meta.CrmAttributeType();
				primaryAttribute.AttributeType.Value        =   AttributeType.Picklist;

                base.Build(wrapper4,publish);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]PickListAttributeBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
        }
    }

    public class One2ManyRelationBuilder
    {

        public const int AttributeSchemaNameMaxLen      =   41; 
        public const int EntityDisplayNameMaxLen        =   82;
        public const int EntitySchemaNameMaxLen         =   39 ;
        public const int RelationshipSchemaNameMaxLen   =   41 ;

        OneToManyMetadata oneToManyRelationship     =   new OneToManyMetadata();
        CreateOneToManyResponse oneToManyResponse   =   null;        
        
		protected string _ReferencedEntity          =   string.Empty;
		protected string _ReferencingEntity         =   string.Empty;

        protected string _SchemaName                =   string.Empty;
        bool _prepared                              =   false;
        bool _TestExists                            =   true;

        AssociatedMenuBehavior _AssociatedMenuBehavior  =   AssociatedMenuBehavior.UseLabel;
        AssociatedMenuGroup _AssociatedMenuGroup    =   AssociatedMenuGroup.Details;
        protected string _AssociatedMenuLabel       =   string.Empty;
        protected int _AssociatedMenuOrder          =   10000;

        CascadeType _CascadeAssign                  =   CascadeType.Cascade;
        CascadeType _CascadeDelete                  =   CascadeType.Cascade;
        CascadeType _CascadeReparent                =   CascadeType.Cascade;
        CascadeType _CascadeShare                   =   CascadeType.Cascade;
        CascadeType _CascadeUnshare                 =   CascadeType.Cascade;

        string _LookupSchemaName                    =   string.Empty;
        string _LookupDisplayName                   =   string.Empty;
        string _LookupDisplayCollectionName         =   string.Empty;
        string _LookupDescription                   =   string.Empty;
        int _langCode                               =   System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
        
        /// <summary>
        /// Set to false when no conditionnal create is necessary
        /// </summary>
        public bool TestExists
        { 
            get
            {
                return _TestExists;
            }
            set
            {
                _TestExists =   value;
            }
        }

        public bool Prepared
        { 
            get
            {
                return _prepared;
            }
        }

        public string SchemaName          
        { 
            get
            {
                return _SchemaName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]One2ManyRelationBuilder SchemaName max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _SchemaName =   value;
            }
        }
        
        public string ReferencedEntity
        { 
            get
            {
                return _ReferencedEntity;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]One2ManyRelationBuilder ReferencedEntity max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _ReferencedEntity =   value;
            }
        }

        public string ReferencingEntity
        { 
            get
            {
                return _ReferencingEntity;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]One2ManyRelationBuilder ReferencingEntity max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _ReferencingEntity =   value;
            }
        }
        
        /// <summary>
        /// Defaults to System.Threading.Thread.CurrentThread.CurrentCulture
        /// </summary>
        public int LangCode
        { 
            get
            {
                return _langCode;
            }
            set
            {
                _langCode =   value;
            }
        }

        public string AssociatedMenuLabel          
        { 
            get
            {
                return _AssociatedMenuLabel;
            }
            set
            {
                if ( value.Length > 200 )
                {
                    string msg  =   "[E]One2ManyRelationBuilder AssociatedMenuLabel max len is 200.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _AssociatedMenuLabel =   value;
            }
        }

        public int AssociatedMenuOrder
        { 
            get
            {
                return _AssociatedMenuOrder;
            }
            set
            {
                _AssociatedMenuOrder =   value;
            }
        }

        public string LookupSchemaName          
        { 
            get
            {
                return _LookupSchemaName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]One2ManyRelationBuilder LookupSchemaName max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _LookupSchemaName =   value;
            }
        }

        public string LookupDisplayName
        { 
            get
            {
                return _LookupDisplayName;
            }
            set
            {
                if ( value.Length > EntityDisplayNameMaxLen )
                {
                    string msg  =   "[E]One2ManyRelationBuilder LookupDisplayName max len is 82.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _LookupDisplayName =   value;
            }
        }

        public string LookupDisplayCollectionName 
        { 
            get
            {
                return _LookupDisplayCollectionName;
            }
            set
            {
                if ( value.Length > EntityDisplayNameMaxLen )
                {
                    string msg  =   "[E]One2ManyRelationBuilder LookupDisplayCollectionName max len is 82.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _LookupDisplayCollectionName =   value;
            }
        }

        public string LookupDescription
        { 
            get
            {
                return _LookupDescription;
            }
            set
            {
                _LookupDescription    =   value;
            }
        }

        public InternalAssociatedMenuBehavior MenuBehavior  
        { 
            get
            {
                return (InternalAssociatedMenuBehavior)(int)_AssociatedMenuBehavior;
            }
            set
            {
                _AssociatedMenuBehavior = (AssociatedMenuBehavior)(int)value;
            }
        }
        
        public InternalAssociatedMenuGroup MenuGroup
        { 
            get
            {
                return (InternalAssociatedMenuGroup)(int)_AssociatedMenuGroup;
            }
            set
            {
                _AssociatedMenuGroup = (AssociatedMenuGroup)(int)value;
            }
        }
        
        public CascadeInternalType CascadeAssign
        { 
            get
            {
                return (CascadeInternalType)(int)_CascadeAssign;
            }
            set
            {
                _CascadeAssign = (CascadeType)(int)value;
            }
        }
        
        public CascadeInternalType CascadeDelete
        { 
            get
            {
                return (CascadeInternalType)(int)_CascadeDelete;
            }
            set
            {
                _CascadeDelete = (CascadeType)(int)value;
            }
        }

        public CascadeInternalType CascadeReparent
        { 
            get
            {
                return (CascadeInternalType)(int)_CascadeReparent;
            }
            set
            {
                _CascadeReparent = (CascadeType)(int)value;
            }
        }

        public CascadeInternalType CascadeShare
        { 
            get
            {
                return (CascadeInternalType)(int)_CascadeShare;
            }
            set
            {
                _CascadeShare = (CascadeType)(int)value;
            }
        }

        public CascadeInternalType CascadeUnshare
        { 
            get
            {
                return (CascadeInternalType)(int)_CascadeUnshare;
            }
            set
            {
                _CascadeUnshare = (CascadeType)(int)value;
            }
        }


        /// <summary>
        /// Return value after Build
        /// </summary>
        public Guid RelationshipId
        {
            get
            {
                if (oneToManyResponse != null)
                    return oneToManyResponse.RelationshipId.Value;
                return Guid.Empty;
            }
        }

        /// <summary>
        /// Return value after Build
        /// </summary>
        public Guid AttributeId
        {
            get
            {
                if (oneToManyResponse != null)
                    return oneToManyResponse.AttributeId.Value;
                return Guid.Empty;
            }
        }
            
        /// <summary>
		/// The ReferencedEntity entity will be the 'one' in this one-to-many relationship
		/// The ReferencingEntity entity will be the 'many' in this one-to-many relationship
        /// </summary>
        public One2ManyRelationBuilder(string schemaName,string referencedEntity,string referencingEntity,int langCode,
            string lookupSchemaName,string lookupDisplayName,string lookupDescription,string associatedMenuLabel)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]One2ManyRelationBuilder Ctor BEG SchemaName: {0}, ReferencedEntity: {1}, ReferencingEntity: {2}, LangCode: {3}, lookupSchemaName: {4}, lookupDisplayName: {5}",
                    new object[]{schemaName,referencedEntity,referencingEntity,langCode,lookupSchemaName,lookupDisplayName}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            SchemaName              =   schemaName;
            ReferencedEntity        =   referencedEntity;
            ReferencingEntity       =   referencingEntity;
            if ( langCode != -1 )
                _langCode           =   langCode;
            AssociatedMenuLabel     =   associatedMenuLabel;
            LookupSchemaName        =   lookupSchemaName;
            LookupDisplayName       =   lookupDisplayName;
            if ( !string.IsNullOrEmpty(lookupDescription) )
                LookupDescription   =   lookupDescription;
            else LookupDescription  =   string.Format("Created by AddonNice on {0}.", DateTime.Now);
        }
        
        public virtual string Prepare(CRMWrapperBase wrapper4,bool useBr)
        {
            if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]One2ManyRelationBuilder Prepare BEG _Prepared: {0}",_prepared),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            if ( _prepared )
                return string.Empty;
            StringBuilder sb                                        =   new StringBuilder();
            try
            {
                string currentPrefix                                =   CrmStr.AdnPrefix;
                string oldPrefix                                    =   wrapper4.SchemaNamePrefix;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]One2ManyRelationBuilder Prepare oldPrefix: {0}",oldPrefix),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                
                string wschemaName                                  =   SchemaName.Replace(" ",string.Empty);
                if ( !wschemaName.StartsWith(currentPrefix+"_") )
                    wschemaName                                     =   string.Format("{0}_{1}",currentPrefix,wschemaName);
                SchemaName                                          =   wschemaName; // to bring back changes to caller

                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]One2ManyRelationBuilder Prepare SchemaName: {0}",SchemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                
                wschemaName                                         =   LookupSchemaName.Replace(" ",string.Empty);
                if ( !wschemaName.StartsWith(currentPrefix+"_") )
                    wschemaName                                     =   string.Format("{0}_{1}",currentPrefix,wschemaName);
                LookupSchemaName                                    =   wschemaName; // to bring back changes to caller

                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]One2ManyRelationBuilder Prepare LookupSchemaName: {0}",LookupSchemaName),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                string nlstr                                        =   Environment.NewLine;
                if ( useBr )
                        nlstr                                       =   CrmStr.strBr;

                sb.AppendFormat("SchemaName: {0}, lookupSchemaName: {1}, lookupDisplayName: {2}{3}",
                    new object[]{SchemaName,LookupSchemaName,LookupDisplayName,nlstr});
                
                _prepared                                           =   true;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine("[V]One2ManyRelationBuilder Prepare END.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
		    }
		    catch (Exception ex)
		    {
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AttributeBuilder Prepare ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
		    }
            return sb.ToString();
        }


        public void Build(CRMWrapperBase wrapper4, bool publish)
        {
            string DefaultDescription = string.Format("Created by AddonNice on {0}.", DateTime.Now);
            try
            {
                string currentPrefix                                =   CrmStr.AdnPrefix;
                string oldPrefix                                    =   wrapper4.SchemaNamePrefix;
                if (CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]One2ManyRelationBuilder Build BEG oldPrefix: {0}",oldPrefix),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                bool changed                                        =   false;
                // TD Get AddonNice prefix from settings
                if (!oldPrefix.Equals(currentPrefix))
                {
                    wrapper4.Util.UpdateSchemaPrefix(currentPrefix);
                    changed                                         =   true;
                }

                if ( !_prepared )
                    Prepare(wrapper4,false);

                // if test is requested
                if ( TestExists )
                {
                    try
                    {
                        InternalAttributeMetadata exatt   =  wrapper4.adminRetrieveAttributeMetadata(ReferencingEntity,LookupSchemaName);
			            if ( CRMMetaTrace.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]One2ManyRelationBuilder Build END LookupSchemaName: {0} existing in {1} skipping create.",
                                LookupSchemaName,ReferencingEntity),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                        if ( changed )
                            wrapper4.Util.UpdateSchemaPrefix(oldPrefix);
                        return;
                    }
                    catch (CRMNotFoundException)
		            {
			            if ( CRMMetaTrace.Sw.TraceVerbose )
                            Trace.WriteLine( "[V]AttributeBuilder Build TestExists doesn't exist.",(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                        // Normal we continue with create
		            }
                    catch (Exception ex)
		            {
			            if ( CRMMetaTrace.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AttributeBuilder Build TestExists ex : {0}", ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                        // Normal we continue with create
		            }
                }

                // The ReferencedEntity entity will be the 'one' in this one-to-many relationship
				oneToManyRelationship.ReferencedEntity              =   ReferencedEntity;

				// The ReferencingEntity entity will be the 'many' in this one-to-many relationship
				oneToManyRelationship.ReferencingEntity             =   ReferencingEntity;

				// Set the metadata properties
				oneToManyRelationship.SchemaName                    =   SchemaName;
				oneToManyRelationship.AssociatedMenuBehavior        =   new CrmAssociatedMenuBehavior();
				oneToManyRelationship.AssociatedMenuBehavior.Value  =   _AssociatedMenuBehavior;
				oneToManyRelationship.AssociatedMenuGroup           =   new CrmAssociatedMenuGroup();
				oneToManyRelationship.AssociatedMenuGroup.Value     =   _AssociatedMenuGroup;
				oneToManyRelationship.AssociatedMenuLabel           =   CRMUtil4.CreateSingleLabel(AssociatedMenuLabel, LangCode);
				oneToManyRelationship.AssociatedMenuOrder           =   new CrmNumber();
				oneToManyRelationship.AssociatedMenuOrder.Value     =   AssociatedMenuOrder;
				
				// Make the relationship behaviour 'parental' by setting all cascade properties to 'Cascade'
				oneToManyRelationship.CascadeAssign                 =   new CrmCascadeType();
				oneToManyRelationship.CascadeAssign.Value           =   _CascadeAssign;
				oneToManyRelationship.CascadeDelete                 =   new CrmCascadeType();
				oneToManyRelationship.CascadeDelete.Value           =   _CascadeDelete;
				oneToManyRelationship.CascadeReparent               =   new CrmCascadeType();
				oneToManyRelationship.CascadeReparent.Value         =   _CascadeReparent;
				oneToManyRelationship.CascadeShare                  =   new CrmCascadeType();
				oneToManyRelationship.CascadeShare.Value            =   _CascadeShare;
				oneToManyRelationship.CascadeUnshare                =   new CrmCascadeType();
				oneToManyRelationship.CascadeUnshare.Value          =   _CascadeUnshare;

				// Create the request 
				CreateOneToManyRequest createRelationship           =   new CreateOneToManyRequest();

				// The 'many' campaign entities will need to store the id to the 'one' account they are related to.
				// So we will now create a lookup to store that id.
				createRelationship.Lookup                           =   new LookupAttributeMetadata();

				// Set the lookup properties
				createRelationship.Lookup.SchemaName                =   LookupSchemaName;
				createRelationship.Lookup.AttributeType             =   new CRM4Meta.CrmAttributeType();
				createRelationship.Lookup.AttributeType.Value       =   AttributeType.Lookup;
				createRelationship.Lookup.DisplayName               =   CRMUtil4.CreateSingleLabel(LookupDisplayName, LangCode);
				createRelationship.Lookup.RequiredLevel             =   new CRM4Meta.CrmAttributeRequiredLevel();
				createRelationship.Lookup.RequiredLevel.Value       =   AttributeRequiredLevel.None;
				createRelationship.Lookup.Description               =   CRMUtil4.CreateSingleLabel(LookupDescription, LangCode);
				createRelationship.Lookup.EntityLogicalName         =   LookupSchemaName;
				createRelationship.OneToManyRelationship            =   oneToManyRelationship;
			
                // Execute the request.
                if ( wrapper4 is CrmWrapper4 )
				    oneToManyResponse                               =   (CreateOneToManyResponse)((CrmWrapper4)wrapper4).adminMetaExecuteRaw(createRelationship);
                if ( changed )
                    wrapper4.Util.UpdateSchemaPrefix(oldPrefix);
			}
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]One2ManyRelationBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
        }
    }

    public class Many2ManyRelationBuilder
    {
        public const int AttributeSchemaNameMaxLen      =   41; 
        public const int EntityDisplayNameMaxLen        =   82;
        public const int EntitySchemaNameMaxLen         =   39 ;
        public const int RelationshipSchemaNameMaxLen   =   41 ;

        ManyToManyMetadata manyToManyRelationship           =   new ManyToManyMetadata();
        CreateManyToManyResponse manyToManyResponse         =   null;        
        
        protected string _SchemaName                        =   string.Empty;

        protected string _Entity1LogicalName                =   string.Empty;
		protected string _Entity2LogicalName                =   string.Empty;
		protected string _IntersectEntitySchemaName         =   string.Empty;

        AssociatedMenuBehavior _Entity1AssociatedMenuBehavior  =   AssociatedMenuBehavior.UseLabel;
        AssociatedMenuGroup _Entity1AssociatedMenuGroup     =   AssociatedMenuGroup.Details;
        protected string _Entity1AssociatedMenuLabel        =   string.Empty;
        protected int _Entity1AssociatedMenuOrder           =   10000;

        AssociatedMenuBehavior _Entity2AssociatedMenuBehavior  =   AssociatedMenuBehavior.UseLabel;
        AssociatedMenuGroup _Entity2AssociatedMenuGroup     =   AssociatedMenuGroup.Details;
        protected string _Entity2AssociatedMenuLabel        =   string.Empty;
        protected int _Entity2AssociatedMenuOrder           =   10000;

        int _langCode                       =   System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
        
        public string SchemaName          
        { 
            get
            {
                return _SchemaName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]MetaDataBuilder SchemaName max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _SchemaName =   value;
            }
        }

        public string Entity1LogicalName          
        { 
            get
            {
                return _Entity1LogicalName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]Many2ManyRelationBuilder SchemaName max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _Entity1LogicalName =   value;
            }
        }

        public string Entity2LogicalName          
        { 
            get
            {
                return _Entity2LogicalName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]Many2ManyRelationBuilder SchemaName max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _Entity2LogicalName =   value;
            }
        }

        public string IntersectEntitySchemaName
        { 
            get
            {
                return _IntersectEntitySchemaName;
            }
            set
            {
                if ( value.Length > EntitySchemaNameMaxLen )
                {
                    string msg  =   "[E]Many2ManyRelationBuilder SchemaName max len is 39.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _IntersectEntitySchemaName =   value;
            }
        }
        /// <summary>
        /// Defaults to System.Threading.Thread.CurrentThread.CurrentCulture
        /// </summary>
        public int LangCode
        { 
            get
            {
                return _langCode;
            }
            set
            {
                _langCode =   value;
            }
        }

        public string Entity1AssociatedMenuLabel          
        { 
            get
            {
                return _Entity1AssociatedMenuLabel;
            }
            set
            {
                if ( value.Length > 200 )
                {
                    string msg  =   "[E]Many2ManyRelationBuilder Entity1AssociatedMenuLabel max len is 200.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _Entity1AssociatedMenuLabel =   value;
            }
        }

        public int Entity1AssociatedMenuOrder
        { 
            get
            {
                return _Entity1AssociatedMenuOrder;
            }
            set
            {
                _Entity1AssociatedMenuOrder =   value;
            }
        }

        public InternalAssociatedMenuBehavior Entity1AssociatedMenuBehavior  
        { 
            get
            {
                return (InternalAssociatedMenuBehavior)(int)_Entity1AssociatedMenuBehavior;
            }
            set
            {
                _Entity1AssociatedMenuBehavior = (AssociatedMenuBehavior)(int)value;
            }
        }
        
        public InternalAssociatedMenuGroup Entity1AssociatedMenuGroup
        { 
            get
            {
                return (InternalAssociatedMenuGroup)(int)_Entity1AssociatedMenuGroup;
            }
            set
            {
                _Entity1AssociatedMenuGroup = (AssociatedMenuGroup)(int)value;
            }
        }
        

        public string Entity2AssociatedMenuLabel          
        { 
            get
            {
                return _Entity2AssociatedMenuLabel;
            }
            set
            {
                if ( value.Length > 200 )
                {
                    string msg  =   "[E]Many2ManyRelationBuilder Entity2AssociatedMenuLabel max len is 200.";
                    if ( CRMMetaTrace.Sw.TraceError)
                        Trace.WriteLine( msg,(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                    throw new ArgumentException(msg);
                }
                _Entity2AssociatedMenuLabel =   value;
            }
        }

        public int Entity2AssociatedMenuOrder
        { 
            get
            {
                return _Entity2AssociatedMenuOrder;
            }
            set
            {
                _Entity2AssociatedMenuOrder =   value;
            }
        }

        public InternalAssociatedMenuBehavior Entity2AssociatedMenuBehavior  
        { 
            get
            {
                return (InternalAssociatedMenuBehavior)(int)_Entity2AssociatedMenuBehavior;
            }
            set
            {
                _Entity2AssociatedMenuBehavior = (AssociatedMenuBehavior)(int)value;
            }
        }
        
        public InternalAssociatedMenuGroup Entity2AssociatedMenuGroup
        { 
            get
            {
                return (InternalAssociatedMenuGroup)(int)_Entity2AssociatedMenuGroup;
            }
            set
            {
                _Entity2AssociatedMenuGroup = (AssociatedMenuGroup)(int)value;
            }
        }
        
        /// <summary>
        /// Return value after Build
        /// </summary>
        public Guid ManyToManyRelationshipId
        {
            get
            {
                if (manyToManyResponse != null)
                    return manyToManyResponse.ManyToManyRelationshipId.Value;
                return Guid.Empty;
            }
        }
            
        public Many2ManyRelationBuilder(string schemaName,string entity1LogicalName,string entity2LogicalName,int langCode)
        {
            if ( CRMMetaTrace.Sw.TraceVerbose || InstallTraceSwitchW.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]Many2ManyRelationBuilder Ctor BEG SchemaName: {0}, Entity1: {1}, Entity2: {2}, LangCode: {3}",
                    new object[]{schemaName,entity1LogicalName,entity2LogicalName,langCode}),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
            SchemaName              =   schemaName;
            Entity1LogicalName      =   entity1LogicalName;
            Entity2LogicalName      =   entity2LogicalName;
            if ( langCode != -1 )
                _langCode   =   langCode;
        }
        
        public void Build(CRMWrapperBase wrapper4, bool publish)
        {
            string DefaultDescription = string.Format("Created by AddonNice on {0}.", DateTime.Now);
            try
            {
				manyToManyRelationship.SchemaName                           = SchemaName;

				// Set the metadata properties

				manyToManyRelationship.Entity1LogicalName                   =   Entity1LogicalName;
				manyToManyRelationship.Entity1AssociatedMenuBehavior        =   new CrmAssociatedMenuBehavior();
				manyToManyRelationship.Entity1AssociatedMenuBehavior.Value  =   _Entity1AssociatedMenuBehavior;
				manyToManyRelationship.Entity1AssociatedMenuGroup           =   new CrmAssociatedMenuGroup();
				manyToManyRelationship.Entity1AssociatedMenuGroup.Value     =   _Entity1AssociatedMenuGroup;
				manyToManyRelationship.Entity1AssociatedMenuLabel           =   CRMUtil4.CreateSingleLabel(Entity1AssociatedMenuLabel, LangCode);
				manyToManyRelationship.Entity1AssociatedMenuOrder           =   new CrmNumber();
				manyToManyRelationship.Entity1AssociatedMenuOrder.Value     =   Entity1AssociatedMenuOrder;
				

				manyToManyRelationship.Entity2LogicalName                   =   Entity2LogicalName;
				manyToManyRelationship.Entity2AssociatedMenuBehavior        =   new CrmAssociatedMenuBehavior();
				manyToManyRelationship.Entity2AssociatedMenuBehavior.Value  =   _Entity2AssociatedMenuBehavior;
				manyToManyRelationship.Entity2AssociatedMenuGroup           =   new CrmAssociatedMenuGroup();
				manyToManyRelationship.Entity2AssociatedMenuGroup.Value     =   _Entity2AssociatedMenuGroup;
				manyToManyRelationship.Entity2AssociatedMenuLabel           =   CRMUtil4.CreateSingleLabel(Entity2AssociatedMenuLabel, LangCode);
				manyToManyRelationship.Entity2AssociatedMenuOrder           =   new CrmNumber();
				manyToManyRelationship.Entity2AssociatedMenuOrder.Value     =   Entity2AssociatedMenuOrder;
				
				CreateManyToManyRequest createRelationship                  =   new CreateManyToManyRequest();
				
				// Microsoft CRM 4.0 uses a linker behind the scenes to create a many-to-many relationship.
				// This is the name given to that linker entity.
				createRelationship.IntersectEntitySchemaName                =   IntersectEntitySchemaName;
				createRelationship.ManyToManyRelationship                   =   manyToManyRelationship;
				
			
                // Execute the request.
                if ( wrapper4 is CrmWrapper4 )
				    manyToManyResponse                           =   (CreateManyToManyResponse)((CrmWrapper4)wrapper4).adminMetaExecuteRaw(createRelationship);
			}
			catch (Exception ex)
			{
                if ( CRMMetaTrace.Sw.TraceError)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]Many2ManyRelationBuilder Build ex: {0}",ex),(CRMMetaTrace.Sw.TraceVerbose) ?  CRMMetaTrace.Sw.Info:  InstallTraceSwitchW.Sw.Info);
                throw;
			}
        }
    }
}
